///////////////////////////////////////////////////////////////////////////////
// File:        TcpConnectionStream.cc
// Author:      671643387@qq.com
// Description:
///////////////////////////////////////////////////////////////////////////////

#include <memory.h>
#include "common/TcpConnectionStream.hpp"
using namespace monkey::common;

///////////////////////////////////////////////////////////////////////////////

#define __INN_MIN(a, b) ((a) > (b)) ? (b) : (a)

///////////////////////////////////////////////////////////////////////////////

TcpConnectionStream::TcpConnectionStream(TcpConnection& conn)
: conn_(conn)
, buffSize_(TCP_CONN_STREAM_SIZE)
, begIndex_(0)
, endIndex_(0)
, size_(0)
{

}

TcpConnectionStream::~TcpConnectionStream()
{

}

unsigned int TcpConnectionStream::Write(const char* buf, unsigned int length)
{
    if (length == 0)
        return 0;

    unsigned int capacity = buffSize_;
    unsigned int bytes_to_write = __INN_MIN(length, capacity - size_);

    if (bytes_to_write <= capacity - endIndex_)
    {
        memcpy(&buffer_[endIndex_], buf, bytes_to_write);
        endIndex_ += bytes_to_write;
        if (endIndex_ == capacity)
            endIndex_ = 0;
    }
    else
    {
        unsigned int size_1 = capacity - endIndex_;
        memcpy(&buffer_[endIndex_], buf, size_1);
        unsigned int size_2 = bytes_to_write - size_1;
        memcpy(&buffer_[0], buf + size_1, size_2);
        endIndex_ = size_2;
    }

    size_ += bytes_to_write;
    return bytes_to_write;
}

unsigned int TcpConnectionStream::Read(char* buf, unsigned int length)
{
    if (length == 0)
        return 0;

    unsigned int capacity = buffSize_;
    unsigned int bytes_to_read = __INN_MIN(length, size_);

    if (bytes_to_read <= capacity - begIndex_)
    {
        memcpy(buf, &buffer_[begIndex_], bytes_to_read);
        begIndex_ += bytes_to_read;
        if (begIndex_ == capacity)
            begIndex_ = 0;
    }
    else
    {
        unsigned int size_1 = capacity - begIndex_;
        memcpy(buf, &buffer_[begIndex_], size_1);
        unsigned int size_2 = bytes_to_read - size_1;
        memcpy(buf + size_1, &buffer_[0], size_2);
        begIndex_ = size_2;
    }

    size_ -= bytes_to_read;
    return bytes_to_read;
}

unsigned int TcpConnectionStream::Peek(char* buf, unsigned int length)
{
    if (length == 0)
        return 0;

    unsigned int capacity = buffSize_;
    unsigned int bytes_to_read = __INN_MIN(length, size_);

    if (bytes_to_read <= capacity - begIndex_)
    {
        memcpy(buf, &buffer_[begIndex_], bytes_to_read);
    }
    else
    {
        unsigned int size_1 = capacity - begIndex_;
        memcpy(buf, &buffer_[begIndex_], size_1);
        unsigned int size_2 = bytes_to_read - size_1;
        memcpy(buf + size_1, &buffer_[0], size_2);
    }
    return bytes_to_read;
}

unsigned int TcpConnectionStream::Skip(unsigned int length)
{
    if (length == 0)
        return 0;

    unsigned int capacity = buffSize_;
    unsigned int bytes_to_read = __INN_MIN(length, size_);

    if (bytes_to_read <= capacity - begIndex_)
    {
        begIndex_ += bytes_to_read;
        if (begIndex_ == capacity)
            begIndex_ = 0;
    }
    else
    {
        unsigned int size_1 = capacity - begIndex_;
        unsigned int size_2 = bytes_to_read - size_1;
        begIndex_ = size_2;
    }

    size_ -= bytes_to_read;
    return bytes_to_read;
}